<?php
/**
 * FastApp.
 * 1/23/25
 * @Author deepsea
 * @Contact (telegram:deepsea159)
 */

namespace App\Fastapp\Api\Service;

use App\Fastapp\Api\Service\Account\AccountService;
use App\Fastapp\Model\AccountOtherRelated;

class Telegram
{
    public static function checkTelegramAuthorization(array $auth_data, string $bot_token): bool
    {
        if (!isset($auth_data['hash'])) return false;
        $check_hash = $auth_data['hash'];
        unset($auth_data['hash']);
        if (isset($auth_data['login_type'])) unset($auth_data['login_type']);
        if (isset($auth_data['direct'])) unset($auth_data['direct']);
        $data_check_arr = [];
        foreach ($auth_data as $key => $value) $data_check_arr[] = $key . '=' . $value;
        sort($data_check_arr);
        $data_check_string = implode("\n", $data_check_arr);
        $secret_key = hash('sha256', $bot_token, true);
        $hash = hash_hmac('sha256', $data_check_string, $secret_key);
        if (strcmp($hash, $check_hash) !== 0) return false;
        if ((time() - $auth_data['auth_date']) > 86400) return false;
        return true;
    }

    public static function verifyTelegramHash(string $initData, string $botToken): bool|array
    {
        parse_str($initData, $result);
        parse_str($result['tgWebAppData'], $data);
        if (!isset($data['hash'])) return false;
        $receivedHash = $data['hash'];
        unset($data['hash']);
        ksort($data);
        $checkString = '';
        foreach ($data as $key => $value) {
            $checkString .= "{$key}={$value}\n";
        }
        $checkString = rtrim($checkString, "\n");
        $secretKey = hash_hmac('sha256', $botToken, 'WebAppData', true);
        $calculatedHash = hash_hmac('sha256', $checkString, $secretKey);
        if (hash_equals($calculatedHash, $receivedHash)) {
            $data['user'] = json_decode($data['user'], true);
            return $data;
        }
        return false;
    }

    public static function getUid(string $from_id, int|string $account_type): int
    {
        $uid = redis()->hGet('tg', $from_id);
        if ($uid) return (int)$uid;
        $uid = (int)AccountOtherRelated::query()
            ->where(['unique_code' => $from_id, 'account_type' => $account_type])
            ->value('user_id');
        redis()->hSet('tg', $from_id, $uid);
        return $uid;
    }

    public static function createUser(array $data): int
    {
        if (isset($data['username'])) {
            $data['nickname'] = $data['username'];
            unset($data['username']);
        }
        $service = new AccountService();
        $ac = $service->create($data);
        AccountOtherRelated::query()->create([
            'unique_code' => $data['id'],
            'related_type' => AccountOtherRelated::TYPE_TELEGRAM,
            'account_type' => $ac->type,
            'user_id' => $ac->gene_id
        ]);
        redis()->hSet('tg', (string)$data['id'], $ac->gene_id);
        set_user_cache(['tgid' => $data['id']], $ac->gene_id);
        return $ac->gene_id;
    }

    public static function parseEntity(array $entities, string $text): array
    {
        $cmds = $mention = [];
        foreach ($entities as $entity) {
            if ($entity['type'] == 'mention') $mention = $entity;
            if ($entity['type'] == 'bot_command') $cmds[] = substr($text, $entity['offset'], $entity['length']);
        }
        if ($mention) $text = substr_replace($text, "", $mention['offset'], $mention['length']);
        $text = str_replace($cmds, "", $text);
        return [$cmds, trim($text), $mention];
    }
}